package com.wang.springbootinit.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.springbootinit.common.ErrorCode;
import com.wang.springbootinit.exception.BusinessException;
import com.wang.springbootinit.mapper.GradeRepository;
import com.wang.springbootinit.mapper.MakeupMapper;
import com.wang.springbootinit.model.dto.MakeupArrangeDTO;
import com.wang.springbootinit.model.dto.MakeupQueryDTO;
import com.wang.springbootinit.model.entity.Grade;
import com.wang.springbootinit.model.entity.Makeup;
import com.wang.springbootinit.model.entity.Student;
import com.wang.springbootinit.model.vo.ExemptionVO;
import com.wang.springbootinit.model.vo.MakeupVO;
import com.wang.springbootinit.service.MakeupService;
import com.wang.springbootinit.service.StudentService;
import com.wang.springbootinit.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toMap;

/**
 * 补考服务实现类
 * 处理补考申请、安排和成绩管理等相关业务逻辑
 */
@Service
@Slf4j
public class MakeupServiceImpl extends ServiceImpl<MakeupMapper, Makeup> implements MakeupService {
    @Autowired
    private MakeupMapper makeupMapper;

    @Autowired
    private StudentService studentService;

    @Autowired
    private UserService userService;

    /**
     * 提交补考申请
     * @param makeup 补考信息
     * @return 是否提交成功
     */
    @Override
    public boolean submitMakeup(Makeup makeup,HttpServletRequest request) {
        Student loginStudent = userService.getLoginStudent(request);
        makeup.setApplyTime(LocalDateTime.now());
        makeup.setExamStatus(0); // 设置为待安排状态
        makeup.setStudentId(loginStudent.getId());
        makeup.setExamLocation("暂未安排");
        int insert = makeupMapper.insert(makeup);
        if (insert > 0) {
            return true;
        }
        throw new BusinessException("报名失败");
    }

    /**
     * 安排补考
     * @param arrangeDTO 补考安排信息，包含考试时间、地点等
     * @return 是否安排成功
     * @throws BusinessException 当补考记录不存在或状态不正确时抛出异常
     */
    @Override
    public boolean arrangeMakeup(MakeupArrangeDTO arrangeDTO) {
        Makeup makeup = makeupMapper.selectById(arrangeDTO.getMakeupId());
        if (makeup == null) {
            throw new BusinessException("补考记录不存在");
        }
        if (makeup.getExamStatus() != 0) {
            throw new BusinessException("该补考已被安排或已完成");
        }

        Makeup update = new Makeup();
        update.setMakeupId(arrangeDTO.getMakeupId());
        update.setExamTime(arrangeDTO.getExamTime());
        update.setExamLocation(arrangeDTO.getExamLocation());
        update.setExamStatus(1);

        int result = makeupMapper.updateById(update);
        if (result > 0) {
            return true;
        }
        throw new BusinessException("安排失败");
    }

    /**
     * 分页查询补考记录
     * @param queryDTO 查询条件，包含学生ID、考试项目、考试状态、时间范围等
     * @return 补考记录分页结果
     */
    @Override
    public Page<MakeupVO> getMakeupPage(MakeupQueryDTO queryDTO) {
        // 创建分页对象
        Page<Makeup> page = new Page<>(queryDTO.getCurrent(), queryDTO.getPageSize());
        
        // 构建查询条件
        LambdaQueryWrapper<Makeup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotNull(queryDTO.getExamStatus()),
                        Makeup::getExamStatus, queryDTO.getExamStatus());
        if(StringUtils.isNotBlank(queryDTO.getStudentNumber())){
            Student student = studentService.getStudentByNumber(queryDTO.getStudentNumber());
            if(ObjectUtil.isNull(student)){
                return new Page<>();
            }
            if(ObjectUtil.isNotNull(student)){
                queryWrapper.eq(Makeup::getStudentId,student.getId());
            }
        }
                        
        // 执行查询
        Page<Makeup> makeupPage = makeupMapper.selectPage(page, queryWrapper);
        if(ObjectUtil.isNull(makeupPage) || CollUtil.isEmpty(makeupPage.getRecords())){
            return new Page<>();
        }
        List<Long> studentIds = makeupPage.getRecords().stream().map(Makeup::getStudentId).collect(Collectors.toList());
        List<Student> studentList = studentService.listByIds(studentIds);
        Map<Long, Student> studentMap = studentList.stream().collect(toMap(Student::getId, Function.identity(), (k1, k2) -> k1));

        List<MakeupVO> makeupVOList = makeupPage.getRecords().stream().map(item -> {
            MakeupVO makeupVO = new MakeupVO();
            BeanUtils.copyProperties(item, makeupVO);
            Student student = studentMap.get(item.getStudentId());
            if (ObjectUtil.isNotNull(student)) {
                makeupVO.setStudentNumber(student.getStudentNumber());
                makeupVO.setStudentName(student.getName());
            }
            return makeupVO;
        }).collect(Collectors.toList());

        Page<MakeupVO> voPage = new Page<>();
        voPage.setSize(makeupPage.getSize());
        voPage.setTotal(makeupPage.getTotal());
        voPage.setSize(makeupPage.getSize());
        voPage.setCurrent(makeupPage.getCurrent());
        voPage.setRecords(makeupVOList);
        return voPage;
    }

    /**
     * 更新补考成绩
     * @param makeupId 补考记录ID
     * @param scoreId 成绩记录ID
     * @return 是否更新成功
     * @throws BusinessException 更新失败时抛出异常
     */
    @Override
    public boolean updateMakeupScore(Long makeupId, Long scoreId) {
        Makeup makeup = new Makeup();
        makeup.setMakeupId(makeupId);
        makeup.setScoreId(scoreId);
        makeup.setExamStatus(2); // 设置为已完成状态
        
        int result = makeupMapper.updateById(makeup);
        if (result > 0) {
            return true;
        }
        throw new BusinessException("更新成绩失败");
    }

    @Override
    public List<MakeupVO> getCurrentList(HttpServletRequest request) {
        Student loginStudent = userService.getLoginStudent(request);
        LambdaQueryWrapper<Makeup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Makeup::getStudentId,loginStudent.getId());
        List<Makeup> makeupList = list(queryWrapper);
        if(CollUtil.isEmpty(makeupList)){
            return new ArrayList<>();
        }

        return makeupList.stream().map(item -> {
            MakeupVO makeupVO = new MakeupVO();
            BeanUtils.copyProperties(item,makeupVO);
            makeupVO.setStudentName(loginStudent.getName());
            makeupVO.setStudentNumber(loginStudent.getStudentNumber());
            return makeupVO;
        }).collect(Collectors.toList());
    }

    /**
     * 获取学生的补考记录列表
     * @param studentId 学生ID
     * @return 补考记录列表
     */
    @Override
    public List<Makeup> getMyMakeups(Long studentId) {
        return Collections.emptyList();
    }

    /**
     * 根据ID获取补考记录详情
     * @param makeupId 补考记录ID
     * @return 补考记录详情
     */
    @Override
    public Makeup getMakeupById(Long makeupId) {
        if (ObjectUtil.isNull(makeupId)) {
            throw new BusinessException("补考记录ID不能为空");
        }
        Makeup makeup = makeupMapper.selectById(makeupId);
        if (ObjectUtil.isNull(makeup)) {
            throw new BusinessException("补考记录不存在");
        }
        return makeup;
    }

    /**
     * 取消补考申请
     * @param makeupId 补考记录ID
     * @return 是否取消成功
     */
    @Override
    public boolean cancelMakeup(Long makeupId) {
        // 获取补考记录
        Makeup makeup = getMakeupById(makeupId);
        
        // 只有待安排状态的补考才能取消
        if (makeup.getExamStatus() != 0) {
            throw new BusinessException("只能取消未安排的补考申请");
        }

        makeup.setExamStatus(3);
        return updateById(makeup);
    }

    @Override
    public Page<Makeup> listMakeupByPage(long current, long pageSize, Long studentId, Integer status) {
        // 创建分页对象
        Page<Makeup> page = new Page<>(current, pageSize);
        // 构建查询条件
        LambdaQueryWrapper<Makeup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Makeup::getApplyTime);
        
        // 添加查询条件（如果有）
        if (studentId != null) {
            queryWrapper.eq(Makeup::getStudentId, studentId);
        }
        if (status != null) {
            queryWrapper.eq(Makeup::getExamStatus, status);
        }
        
        // 执行查询
        return makeupMapper.selectPage(page, queryWrapper);
    }

    @Override
    public boolean audit(MakeupArrangeDTO arrangeDTO) {
        if(ObjectUtil.isNull(arrangeDTO) || ObjectUtil.isNull(arrangeDTO.getMakeupId())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long makeupId = arrangeDTO.getMakeupId();
        Makeup makeup = getById(makeupId);
        if(ObjectUtil.isNull(makeup)){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        makeup.setExamStatus(arrangeDTO.getExamStatus());
        return updateById(makeup);
    }
} 